# -*- coding:UTF-8 -*-
# file   : SplitWindow.py
# time   : 2023/12/5 
# author : panghu
# Desc   :
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import QMainWindow, QPushButton, QWidget, QVBoxLayout, QHBoxLayout, QLabel, \
    QDoubleSpinBox, QGridLayout, QSpinBox, QHeaderView, QTableWidget, QTableWidgetItem, QTextBrowser, QMessageBox, \
    QProgressBar
from moviepy.editor import VideoFileClip
import math
from FileChooser import FileChooser, get_filename_and_extension
import datetime
from datetime import datetime as dt

from VideoSplitter import *


def format_timestamp_with_timezone(timestamp):
    tz_east_8 = datetime.timezone(datetime.timedelta(hours=8))
    dt_object = dt.fromtimestamp(timestamp, tz_east_8)
    formatted_date = dt_object.strftime("%Y-%m-%d %H:%M:%S")
    return formatted_date


class SplitTimeWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("时长切割")
        self.video_path = ""
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        self.splitter = VideoSplitter()
        self.splitter.finished.connect(self.on_finished)
        v_layout = QVBoxLayout()
        h_layout = QHBoxLayout()
        title_label = QLabel("设置切割时长，运行后会根据设置的时长将视频切割成若干个片段")
        v_layout.addWidget(title_label)
        time_label = QLabel("时长")
        h_layout.addWidget(time_label)

        self.spin_box = QDoubleSpinBox(self)

        self.spin_box.setMinimum(0.0)
        # spin_box.setMaximum(100.0)
        self.spin_box.setSingleStep(1.0)
        self.spin_box.setDecimals(2)
        self.spin_box.setValue(10)
        h_layout.addWidget(self.spin_box)
        v_layout.addLayout(h_layout)

        v_layout.addWidget(QLabel("选择视频文件"))
        file_choose = FileChooser(
            file_type="视频",
            file_selected_callback=lambda file_path: self.update_path(file_path)
        )
        v_layout.addWidget(file_choose)

        grid_layout = QGridLayout()

        self.reset_button = QPushButton("重置")
        self.reset_button.clicked.connect(self.reset_event)
        self.start_button = QPushButton("开始")
        self.start_button.clicked.connect(self.start_event)

        grid_layout.addWidget(self.reset_button, *(0, 0))
        grid_layout.addWidget(self.start_button, *(0, 1))

        button_h_layout = QHBoxLayout()
        button_h_layout.addStretch(1)
        button_h_layout.addLayout(grid_layout)
        button_h_layout.addStretch(1)

        v_layout.addLayout(button_h_layout)

        central_widget.setLayout(v_layout)

    def update_path(self, file_path):
        self.video_path = file_path

    def reset_event(self):
        self.spin_box.setValue(10)

    def start_event(self):
        if len(self.video_path) == 0:
            show_dialog(self, "提示", "请选择要切割的视频")
            return
        file_name, ext, _ = get_filename_and_extension(self.video_path)
        show_dialog(self, "提示", f"开始切割视频：{file_name}{ext}")
        self.reset_button.setEnabled(False)
        self.start_button.setEnabled(False)
        self.spin_box.setEnabled(False)
        threading.Thread(target=self.splitter.split_duration, args=(self.video_path, self.spin_box.value())).start()

    def on_finished(self, info):
        is_success = info["isSuccess"]
        file_name, ext, _ = get_filename_and_extension(self.video_path)
        show_dialog(self, "提示", "视频{}切割{}".format(file_name, "完成" if is_success else "失败"))
        self.spin_box.setEnabled(True)
        self.reset_button.setEnabled(True)
        self.start_button.setEnabled(True)


class SplitCountWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.video_path = ""
        self.setWindowTitle("分段切割")
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        v_layout = QVBoxLayout()
        h_layout = QHBoxLayout()
        title_label = QLabel("设置切割的段，运行后会将视频切割为设置的段数")
        v_layout.addWidget(title_label)
        time_label = QLabel("数量")
        h_layout.addWidget(time_label)

        self.spin_box = QSpinBox(self)

        self.spin_box.setMinimum(2)
        # spin_box.setMaximum(100.0)
        self.spin_box.setSingleStep(1)
        self.spin_box.setValue(5)
        h_layout.addWidget(self.spin_box)
        v_layout.addLayout(h_layout)

        v_layout.addWidget(QLabel("选择视频文件"))
        file_choose = FileChooser(
            file_type="视频",
            file_selected_callback=lambda file_path: self.update_path(file_path)
        )
        v_layout.addWidget(file_choose)

        self.splitter = VideoSplitter()
        self.splitter.finished.connect(self.on_finished)

        grid_layout = QGridLayout()

        self.reset_button = QPushButton("重置")
        self.reset_button.clicked.connect(self.reset_event)
        self.start_button = QPushButton("开始")
        self.start_button.clicked.connect(self.start_event)

        grid_layout.addWidget(self.reset_button, *(0, 0))
        grid_layout.addWidget(self.start_button, *(0, 1))

        button_h_layout = QHBoxLayout()
        button_h_layout.addStretch(1)
        button_h_layout.addLayout(grid_layout)
        button_h_layout.addStretch(1)

        v_layout.addLayout(button_h_layout)

        central_widget.setLayout(v_layout)

    def update_path(self, file_path):
        self.video_path = file_path

    def reset_event(self):
        self.spin_box.setValue(5)

    def start_event(self):
        if len(self.video_path) == 0:
            show_dialog(self, "提示", "请选择要切割的视频")
            return
        file_name, ext, _ = get_filename_and_extension(self.video_path)
        show_dialog(self, "提示", f"开始切割视频：{file_name}{ext}")
        show_dialog(self, "提示", f"切割路径:{self.video_path}")
        self.reset_button.setEnabled(False)
        self.start_button.setEnabled(False)
        self.spin_box.setEnabled(False)
        threading.Thread(target=self.splitter.split_num, args=(self.video_path, self.spin_box.value())).start()

    def on_finished(self, info):
        is_success = info["isSuccess"]
        file_name, ext, _ = get_filename_and_extension(self.video_path)
        show_dialog(self, "提示", "视频{}切割{}".format(file_name, "完成" if is_success else "失败"))
        self.spin_box.setEnabled(True)
        self.reset_button.setEnabled(True)
        self.start_button.setEnabled(True)


def read_file(file_path, dispose=None):
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            content = file.read()
            if dispose is None:
                return content, file_path
            data = dispose(content)
            file.close()
            return data, file_path
    except Exception as e:
        # print(f"读取文件时发生错误: {e}")
        return None


def parse_srt(srt_content):
    subtitles = []
    entries = srt_content.split('\n\n')
    for entry in entries:
        lines = entry.strip().split('\n')
        if len(lines) >= 3:
            time_range = lines[1].split(' --> ')
            start_time, end_time = time_range[0], time_range[1]
            content = ' '.join(lines[2:])
            subtitles.append((start_time, end_time, content))
    return subtitles


class SplitSrtWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.video_path = ""
        self.subtitles = []
        self.setWindowTitle("字幕切割")
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        v_layout = QVBoxLayout()

        h_layout = QHBoxLayout()
        grid_layout = QGridLayout()
        title_label = QLabel("根据字幕文件进行视频切割")
        grid_layout.addWidget(title_label, *(0, 0))

        self.start_button = QPushButton("开始切割")
        self.start_button.setEnabled(False)
        self.start_button.clicked.connect(lambda: self.start_task())
        grid_layout.addWidget(self.start_button, *(0, 1))

        h_layout.addLayout(grid_layout)
        v_layout.addLayout(h_layout)

        file_choose = FileChooser(
            check_endswith=lambda file_path: file_path.endswith(".srt"),
            file_filter="SRT Files (*.srt)",
            file_type="字幕",
            file_selected_callback=lambda file_path: self.update_table(
                read_file(file_path, dispose=lambda subtitles: parse_srt(subtitles)))
        )
        file_choose.setMinimumSize(300, 100)

        file_h_layout = QHBoxLayout()
        file_h_layout.addStretch(1)
        file_h_layout.addWidget(file_choose)
        file_h_layout.addStretch(1)

        v_layout.addLayout(file_h_layout)

        v_layout.addWidget(QLabel("选择视频文件"))
        file_choose = FileChooser(
            file_type="视频",
            file_selected_callback=lambda file_path: self.update_path(file_path)
        )
        v_layout.addWidget(file_choose)

        self.splitter = VideoSplitter()
        self.splitter.finished.connect(self.on_finished)

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(["开始时间", "结束时间", "字幕内容"])
        # self.table.setMaximumHeight(300)
        self.table.setMinimumHeight(100)
        # 设置前两列基于内容调整大小，第三列填充剩余空间
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(2, QHeaderView.Stretch)

        v_layout.addWidget(self.table)

        central_widget.setLayout(v_layout)

    def update_path(self, file_path):
        self.video_path = file_path

    def choose_file(self, file_path):
        tmp_list, f_path = read_file(file_path)
        self.update_table(tmp_list)

    def update_table(self, data):
        subtitles, file_path = data
        self.table.clearContents()

        self.table.setRowCount(len(subtitles))
        self.subtitles = subtitles
        self.start_button.setEnabled(len(subtitles) > 0)
        for row, (start_time, end_time, content) in enumerate(subtitles):
            self.table.setItem(row, 0, QTableWidgetItem(start_time))
            self.table.setItem(row, 1, QTableWidgetItem(end_time))
            self.table.setItem(row, 2, QTableWidgetItem(content))

    def start_task(self):
        if len(self.subtitles) == 0:
            show_dialog(self, "提示", "请选择字幕文件")
            return
        if len(self.video_path) == 0:
            show_dialog(self, "提示", "请选择视频文件")
            return
        file_name, ext, _ = get_filename_and_extension(self.video_path)
        show_dialog(self, "提示", f"开始切割视频：{file_name}{ext}")
        threading.Thread(target=self.splitter.split_srt, args=(self.video_path, self.subtitles)).start()

    def on_finished(self, info):
        is_success = info["isSuccess"]
        file_name, ext, _ = get_filename_and_extension(self.video_path)
        show_dialog(self, "提示", "视频{}切割{}".format(file_name, "完成" if is_success else "失败"))
        self.table.setEnabled(True)
        self.start_button.setEnabled(True)


class EditSrtWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.old_subtitles = []
        self.subtitles = []
        self.setWindowTitle("字幕编辑与查看")
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        v_layout = QVBoxLayout()

        file_choose = FileChooser(
            check_endswith=lambda file_path: file_path.endswith(".srt"),
            file_filter="SRT Files (*.srt)",
            file_type="字幕",
            file_selected_callback=lambda file_path: self.update_table(
                read_file(file_path, dispose=lambda subtitles: parse_srt(subtitles)))
        )
        file_choose.setMinimumSize(300, 100)

        file_h_layout = QHBoxLayout()
        file_h_layout.addStretch(1)
        file_h_layout.addWidget(file_choose)
        file_h_layout.addStretch(1)

        v_layout.addLayout(file_h_layout)

        b_h_layout = QHBoxLayout()
        b_h_layout.setSpacing(5)

        self.reset_btn = QPushButton("重置")
        self.reset_btn.setEnabled(False)
        self.reset_btn.clicked.connect(lambda _: self.reset_table)
        b_h_layout.addWidget(self.reset_btn)
        b_h_layout.addStretch(1)
        self.save_btn = QPushButton("保存")
        self.save_btn.setEnabled(False)
        b_h_layout.addWidget(self.save_btn)
        b_h_layout.addStretch(1)
        self.replace_btn = QPushButton("敏感词替换")
        self.replace_btn.setEnabled(False)
        self.replace_btn.clicked.connect(lambda _: self.replace_event)
        b_h_layout.addWidget(self.replace_btn)
        v_layout.addLayout(b_h_layout)

        self.srt_table = QTableWidget()
        self.srt_table.setColumnCount(3)
        self.srt_table.setHorizontalHeaderLabels(["开始时间", "结束时间", "字幕内容"])
        header = self.srt_table.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.ResizeToContents)
        # self.table.setMaximumHeight(300)
        self.srt_table.setMinimumHeight(100)
        self.srt_table.itemChanged.connect(self.on_item_changed)
        v_layout.addWidget(self.srt_table)

        central_widget.setLayout(v_layout)

    def update_table(self, subtitles):
        self.srt_table.clearContents()
        self.srt_table.setRowCount(len(subtitles))
        self.old_subtitles = subtitles
        self.subtitles = subtitles
        could_show = len(subtitles) > 0
        self.reset_btn.setEnabled(could_show)
        self.save_btn.setEnabled(could_show)
        self.replace_btn.setEnabled(could_show)
        self.srt_table.itemChanged.disconnect(self.on_item_changed)
        for row, (start_time, end_time, content) in enumerate(subtitles):
            self.srt_table.setItem(row, 0, QTableWidgetItem(start_time))
            self.srt_table.setItem(row, 1, QTableWidgetItem(end_time))
            self.srt_table.setItem(row, 2, QTableWidgetItem(content))

        self.srt_table.itemChanged.connect(self.on_item_changed)

    def on_item_changed(self, item):
        row = item.row()
        if len(self.subtitles) <= row:
            return
        data = self.subtitles[row]
        data[item.column()] = item.text()

    def reset_table(self):
        self.update_table(self.old_subtitles)

    def replace_event(self):
        pass


def replace_source_dispose(content):
    lines = content.strip().split('\n')
    return [(line.split('→')[0], line.split('→')[1]) for line in lines if '→' in line]


def count_hits(text, substitutions):
    hit_count = {}
    total_hits = 0

    for old, _ in substitutions:
        count = text.count(old)
        if count > 0:
            hit_count[old] = count
            total_hits += count

    return total_hits, hit_count


def show_dialog(window, title, msg):
    msg_box = QMessageBox(window)
    msg_box.setIconPixmap(QPixmap("clip_icon.png"))  # 使用自定义图标
    msg_box.setWindowTitle(title)
    msg_box.setText(msg)
    msg_box.exec()


class ReplaceSrtWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.wait_content = ""
        self.wait_file_path = ""
        self.source_content = []
        self.setWindowTitle("敏感词检测")
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        v_layout = QVBoxLayout()

        title_label = QLabel("选择敏感词(txt格式)->选择要修改的文件(txt、srt格式)->点击修改")
        v_layout.addWidget(title_label)

        self.check_btn = QPushButton("检测")
        self.check_btn.setEnabled(False)
        self.check_btn.clicked.connect(lambda _: self.just_check())
        self.start_btn = QPushButton("检测并替换")
        self.start_btn.setEnabled(False)
        self.start_btn.clicked.connect(lambda _: self.start_task())

        h_layout = QHBoxLayout()
        h_layout.setSpacing(15)
        h_layout.addWidget(self.check_btn)
        h_layout.addStretch(1)
        h_layout.addWidget(self.start_btn)

        v_layout.addLayout(h_layout)

        replace_choose = FileChooser(
            check_endswith=lambda file_path: file_path.endswith(".txt"),
            file_filter="Text Files (*.txt)",
            file_type="敏感词",
            file_selected_callback=lambda file_path: self.get_source(
                read_file(file_path, dispose=lambda content: replace_source_dispose(content)))
        )
        replace_choose.setMinimumSize(300, 100)

        replace_h_layout = QHBoxLayout()
        replace_h_layout.addStretch(1)
        replace_h_layout.addWidget(replace_choose)
        replace_h_layout.addStretch(1)
        v_layout.addLayout(replace_h_layout)

        source_choose = FileChooser(
            check_endswith=lambda file_path: file_path.endswith(".srt") or file_path.endswith(".txt"),
            file_filter="Text Files (*.txt);;SRT Files (*.srt)",
            file_type="替换文件",
            file_selected_callback=lambda file_path: self.get_wait_source(read_file(file_path))
        )
        source_choose.setMinimumSize(300, 100)

        source_h_layout = QHBoxLayout()
        source_h_layout.addStretch(1)
        source_h_layout.addWidget(source_choose)
        source_h_layout.addStretch(1)

        v_layout.addLayout(source_h_layout)

        result_title_label = QLabel("检测结果")
        v_layout.addWidget(result_title_label)

        self.browser = QTextBrowser()
        self.browser.setMaximumHeight(100)
        v_layout.addWidget(self.browser)
        central_widget.setLayout(v_layout)

    def get_source(self, data):
        source, file_path = data
        if source is not None:
            self.source_content = source
        result = self.check_data()
        self.start_btn.setEnabled(result)
        self.check_btn.setEnabled(result)

    def get_wait_source(self, data):
        print(data)
        source, file_path = data
        self.wait_file_path = file_path
        if source is not None:
            self.wait_content = source
        result = self.check_data()
        self.start_btn.setEnabled(result)
        self.check_btn.setEnabled(result)

    def check_data(self):
        return len(self.wait_content) != 0 and len(self.source_content) != 0

    def just_check(self, alone=True):
        total_hits, hit_count = count_hits(self.wait_content, self.source_content)
        time_text = format_timestamp_with_timezone(dt.timestamp(dt.now()))

        hit_text = "\n".join([f"违禁词'{key}':{value}次" for key, value in hit_count.items()])
        text = f"{time_text}:\n共命中违规词{total_hits}次\n{hit_text}"
        self.browser.append(text)
        if alone:
            show_dialog(self, "提示", "违规词检测已完成")

    def start_task(self):
        self.just_check(False)
        if len(self.wait_file_path) == 0:
            return
        file_name, file_ext, folder_path = get_filename_and_extension(self.wait_file_path)
        file = open(self.wait_file_path, 'r', encoding='utf-8')
        file_text = file.read()
        file.close()
        for (key, value) in self.source_content:
            file_text = file_text.replace(key, value)
        print(folder_path)
        new_file_path = f"{folder_path}替换-{file_name}{file_ext}"
        print(new_file_path)
        with open(new_file_path, 'w', encoding='utf-8') as f:
            f.write(file_text)
            f.close()
        show_dialog(self, "提示", "违规词检测并替换已完成")